/* 拿到store的modules */
import { modules } from "./modules";

/* 获取到mutations 结构类型 */
// 匹配到 单个module 下的 mutations
type GetMutation<Module> = Module extends { mutations: infer M } ? M : unknown;
// 获取vuex 所有的mutations模块
type GetMutations<Modules> = {
  [K in keyof Modules]: GetMutation<Modules[K]>;
};
type ModuleMutations = GetMutations<typeof modules>;

/* 获取到 getters 结构类型 */
// 匹配到 单个module 下的 getter
type GetGetter<Moudle> = Moudle extends { getters: infer G } ? G : unknown;
// 获取vuex 所有的getter模块
type GetGetters<Modules> = {
  [K in keyof Modules]: GetGetter<Modules[K]>;
};
type ModuleGettes = GetGetters<typeof modules>;

/* 获取到action 结构类型 */
// 匹配到 单个module 下的 action
type GetAction<Moudle> = Moudle extends { actions: infer A } ? A : unknown;
// 获取vuex 所有的action模块
type GetActions<Modules> = {
  [K in keyof Modules]: GetAction<Modules[K]>;
};
type ModuleActions = GetActions<typeof modules>;

/* Getter/Dispatch智能提示处理 */
// 由于传入的是 keyof 有可能是symbol | number,所以 Prefix & string 取其中的string
type AddPrefix<Prefix, Keys> = `${Prefix & string}/${Keys & string}`;
type GetSpliceKey<Module, Key> = AddPrefix<Key, keyof Module>;
type GetSpliceKeys<Modules> = {
  [K in keyof Modules]: GetSpliceKey<Modules[K], K>;
}[keyof Modules];
type GetFunc<T, A, B> = T[A & keyof T][B & keyof T[A & keyof T]];
type GetSpliceObj<T> = {
  // K extends `${infer A}/${infer B}`   相当于  user/getData  A=>user B=>getData
  [K in GetSpliceKeys<T>]: K extends `${infer A}/${infer B}`
    ? GetFunc<T, A, B>
    : unknown;
};

/* Getters/Mutations/Actons 拼接好 xxx/xxx 的格式  */
type Getters = GetSpliceObj<ModuleGettes>;
type Mutations = GetSpliceObj<ModuleMutations>;
type Actions = GetSpliceObj<ModuleActions>;

// 获取payload 参数类型
type MutationsPayload = {
  // Parameters 获取函数参数
  [K in keyof Mutations]: Parameters<Mutations[K]>[1];
};
interface GetDispatch<T> {
  // 可选参数类型，会自动加上undefined
  <K extends keyof T>(action: K, payload?: T[K]): Promise<unknown>;
}
type Dispatch = GetDispatch<MutationsPayload>;

export { Getters, Actions, Mutations, Dispatch };
export default Getters;
